package ciprian.training;

import java.text.DateFormat;
import java.util.Date;

import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.app.ListFragment;
import android.app.LoaderManager;
import android.content.CursorLoader;
import android.content.Loader;
import android.content.res.Configuration;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract.Contacts;
import android.text.TextUtils;
import android.util.Log;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ScrollView;
import android.widget.SearchView;
import android.widget.SimpleCursorAdapter;
import android.widget.TextView;
import android.widget.SearchView.OnQueryTextListener;

public class MyContactsActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		setContentView(R.layout.main);
	}

	/**
	 * This is a secondary activity, to show what the user has selected when the
	 * screen is not large enough to show it all in one activity.
	 */

	public static class DetailsActivity extends Activity {

		@Override
		protected void onCreate(Bundle savedInstanceState) {
			super.onCreate(savedInstanceState);

			if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
				// If the screen is now in landscape mode, we can show the
				// dialog in-line with the list so we don't need this activity.
				finish();
				return;
			}

			if (savedInstanceState == null) {
				// During initial setup, plug in the details fragment.
				DetailsFragment details = new DetailsFragment();
				details.setArguments(getIntent().getExtras());
				getFragmentManager().beginTransaction()
						.add(android.R.id.content, details).commit();
			}
		}
	}

	public static class CursorLoaderListFragment extends ListFragment implements
			OnQueryTextListener, LoaderManager.LoaderCallbacks<Cursor> {

		// This is the Adapter being used to display the list's data.
		SimpleCursorAdapter mAdapter;

		// If non-null, this is the current filter the user has provided.
		String mCurFilter;

		@Override
		public void onActivityCreated(Bundle savedInstanceState) {
			super.onActivityCreated(savedInstanceState);

			// Give some text to display if there is no data. In a real
			// application this would come from a resource.
			setEmptyText("No phone numbers");

			// We have a menu item to show in action bar.
			setHasOptionsMenu(true);

			// Create an empty adapter we will use to display the loaded data.
			mAdapter = new SimpleCursorAdapter(getActivity(),
					android.R.layout.simple_list_item_2, null, new String[] {
							Contacts.DISPLAY_NAME, Contacts.CONTACT_STATUS },
					new int[] { android.R.id.text1, android.R.id.text2 }, 0);
			setListAdapter(mAdapter);
			getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);

			// Start out with a progress indicator.
			setListShown(false);

			// Prepare the loader. Either re-connect with an existing one,
			// or start a new one.
			getLoaderManager().initLoader(0, null, this);
		}

		@Override
		public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
			// Place an action bar item for searching.
			MenuItem item = menu.add("Search");
			item.setIcon(android.R.drawable.ic_menu_search);
			item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
			SearchView sv = new SearchView(getActivity());
			sv.setOnQueryTextListener(this);
			item.setActionView(sv);
		}

		public boolean onQueryTextChange(String newText) {
			// Called when the action bar search text has changed. Update
			// the search filter, and restart the loader to do a new query
			// with this filter.
			mCurFilter = !TextUtils.isEmpty(newText) ? newText : null;
			getLoaderManager().restartLoader(0, null, this);
			return true;
		}

		@Override
		public boolean onQueryTextSubmit(String query) {
			// Don't care about this.
			return true;
		}

		@Override
		public void onListItemClick(ListView l, View v, int position, long id) {
			// Insert desired behavior here.
			Log.i("FragmentComplexList", "Item clicked: " + id);
			showDetails(position, (int) id);
		}

		/**
		 * Helper function to show the details of a selected item, either by
		 * displaying a fragment in-place in the current UI, or starting a whole
		 * new activity in which it is displayed.
		 */
		void showDetails(int index, int id) {
			// We can display everything in-place with fragments, so update
			// the list to highlight the selected item and show the data.
			getListView().setItemChecked(index, true);

			// Check what fragment is currently shown, replace if needed.
			DetailsFragment details = (DetailsFragment) getFragmentManager()
					.findFragmentById(R.id.details);
			if (details == null || details.getShownContactID() != id) {
				// Make new fragment to show this selection.
				Cursor cur = mAdapter.getCursor();
				cur.moveToPosition(index);
				String name = cur.getString(cur
						.getColumnIndex(Contacts.DISPLAY_NAME));
				String status = cur.getString(cur
						.getColumnIndex(Contacts.CONTACT_STATUS));
				long lastTimeContacted = cur.getLong(cur
						.getColumnIndex(Contacts.LAST_TIME_CONTACTED));
				int timesContacted = cur.getInt(cur
						.getColumnIndex(Contacts.TIMES_CONTACTED));
				details = DetailsFragment.newInstance(id, name, status,
						timesContacted, lastTimeContacted);

				// Execute a transaction, replacing any existing fragment
				// with this one inside the frame.
				FragmentTransaction ft = getFragmentManager()
						.beginTransaction();
				ft.replace(R.id.details, details);
				ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
				ft.commit();
			}
		}

		// These are the Contacts rows that we will retrieve.
		static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] {
				Contacts._ID, Contacts.DISPLAY_NAME, Contacts.CONTACT_STATUS,
				Contacts.TIMES_CONTACTED, Contacts.CONTACT_PRESENCE,
				Contacts.LAST_TIME_CONTACTED, Contacts.PHOTO_ID,
				Contacts.LOOKUP_KEY, };

		public Loader<Cursor> onCreateLoader(int id, Bundle args) {
			// This is called when a new Loader needs to be created. This
			// sample only has one Loader, so we don't care about the ID.
			// First, pick the base URI to use depending on whether we are
			// currently filtering.
			Uri baseUri;
			if (mCurFilter != null) {
				baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,
						Uri.encode(mCurFilter));
			} else {
				baseUri = Contacts.CONTENT_URI;
			}

			// Now create and return a CursorLoader that will take care of
			// creating a Cursor for the data being displayed.
			String select = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND ("
					+ Contacts.HAS_PHONE_NUMBER + "=1) AND ("
					+ Contacts.DISPLAY_NAME + " != '' ))";
			return new CursorLoader(getActivity(), baseUri,
					CONTACTS_SUMMARY_PROJECTION, select, null,
					Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC");
		}

		public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
			// Swap the new cursor in. (The framework will take care of closing
			// the old cursor once we return.)
			mAdapter.swapCursor(data);

			// The list should now be shown.
			if (isResumed()) {
				setListShown(true);
			} else {
				setListShownNoAnimation(true);
			}
		}

		public void onLoaderReset(Loader<Cursor> loader) {
			// This is called when the last Cursor provided to onLoadFinished()
			// above is about to be closed. We need to make sure we are no
			// longer using it.
			mAdapter.swapCursor(null);
		}
	}

	/**
	 * This is the secondary fragment, displaying the details of a particular
	 * item.
	 */

	public static class DetailsFragment extends Fragment {
		public static final String CONTACT_ID_TAG = "id";
		public static final String CONTACT_NAME_TAG = "name";
		public static final String CONTACT_STATUS_TAG = "status";
		public static final String CONTACT_TIMES_CONTACTED_TAG = "times_contacted";
		public static final String CONTACT_LASTTIME_CONTACTED_TAG = "last_time_contacted";

		/**
		 * Create a new instance of DetailsFragment, initialized to show the
		 * text at 'index'.
		 */
		public static DetailsFragment newInstance(int id, String name,
				String status, int timesContacted, long lastTimeContacted) {
			DetailsFragment f = new DetailsFragment();

			// Supply index input as an argument.
			Bundle args = new Bundle();
			args.putInt(CONTACT_ID_TAG, id);
			args.putString(CONTACT_NAME_TAG, name);
			args.putString(CONTACT_STATUS_TAG, (status != null) ? status : "");
			args.putInt(CONTACT_TIMES_CONTACTED_TAG, timesContacted);
			args.putLong(CONTACT_LASTTIME_CONTACTED_TAG, lastTimeContacted);
			f.setArguments(args);

			return f;
		}

		public int getShownContactID() {
			return getArguments().getInt(CONTACT_ID_TAG, 0);
		}

		@Override
		public View onCreateView(LayoutInflater inflater, ViewGroup container,
				Bundle savedInstanceState) {
			if (container == null) {
				// We have different layouts, and in one of them this
				// fragment's containing frame doesn't exist. The fragment
				// may still be created from its saved state, but there is
				// no reason to try to create its view hierarchy because it
				// won't be displayed. Note this is not needed -- we could
				// just run the code below, where we would create and return
				// the view hierarchy; it would just never be used.
				return null;
			}

			ScrollView scroller = new ScrollView(getActivity());
			LinearLayout linear = new LinearLayout(this.getActivity());
			TextView name = new TextView(getActivity());
			TextView status = new TextView(getActivity());
			TextView timesContacted = new TextView(getActivity());
			TextView lastTimeContacted = new TextView(getActivity());
			int padding = (int) TypedValue.applyDimension(
					TypedValue.COMPLEX_UNIT_DIP, 4, getActivity()
							.getResources().getDisplayMetrics());

			name.setPadding(padding, padding, padding, padding);
			status.setPadding(padding, padding, padding, padding);
			timesContacted.setPadding(padding, padding, padding, padding);
			lastTimeContacted.setPadding(padding, padding, padding, padding);

			linear.setOrientation(LinearLayout.VERTICAL);
			linear.addView(name);

			scroller.addView(linear);

			name.setText(getArguments().getString(CONTACT_NAME_TAG));

			if (getArguments().getString(CONTACT_STATUS_TAG).length() > 0) {
				// has status ==> display it
				linear.addView(status);
				status.setText(getArguments().getString(CONTACT_STATUS_TAG));
			}

			linear.addView(timesContacted);
			timesContacted.setText("Contacted "
					+ getArguments().getInt(CONTACT_TIMES_CONTACTED_TAG)
					+ " times");

			if (getArguments().getInt(CONTACT_TIMES_CONTACTED_TAG) > 0) {
				// contacted more than once
				linear.addView(lastTimeContacted);
				Date when = new Date(getArguments().getLong(
						CONTACT_LASTTIME_CONTACTED_TAG));
				DateFormat df = DateFormat.getDateTimeInstance(DateFormat.FULL,
						DateFormat.SHORT);
				lastTimeContacted.setText("Last time on " + df.format(when));
			}

			return scroller;
		}
	}
}